<template>
  <div class="login-container">
    <div class="login-info">
      <div class="title">Fuxi Cloud</div>
      <div class="sub-title">{{ $t("common.system") }}</div>
      <div class="desc">1. {{ $t("common.desc.a") }}</div>
      <div class="desc">2. {{ $t("common.desc.b") }}</div>
      <div class="desc">3. {{ $t("common.desc.c") }}</div>
      <div class="desc">4. {{ $t("common.desc.d") }}</div>
      <div class="desc">5. {{ $t("common.desc.e") }}</div>
      <div class="desc">6. {{ $t("common.desc.f") }}</div>
      <div class="desc">7. {{ $t("common.desc.g") }}</div>
      <div class="desc">8. {{ $t("common.desc.h") }}</div>
    </div>
    <el-form
      ref="loginForm"
      :model="loginForm"
      :rules="rules"
      class="login-form"
      autocomplete="off"
      label-position="left"
    >
      <div class="title-container">
        <h3 class="title">
          {{ $t("login.title") }}
        </h3>
        <lang-select class="set-language" />
      </div>
      <span v-if="login.type === 'up'">
        <el-form-item prop="username">
          <el-input
            ref="username"
            v-model="loginForm.username"
            :placeholder="$t('login.username')"
            prefix-icon="el-icon-user"
            name="username"
            type="text"
            autocomplete="off"
            @keyup.enter.native="handleLogin"
          />
        </el-form-item>
        <el-form-item prop="password">
          <el-input
            ref="password"
            v-model="loginForm.password"
            prefix-icon="el-icon-key"
            type="password"
            :placeholder="$t('login.password')"
            name="password"
            autocomplete="off"
            :show-password="true"
            @keyup.enter.native="handleLogin"
          />
        </el-form-item>
        <el-form-item prop="code" class="code-input">
          <el-input
            ref="code"
            v-model="loginForm.code"
            prefix-icon="el-icon-lock"
            :placeholder="$t('login.code')"
            name="code"
            type="text"
            autocomplete="off"
            style="width: 70%"
            @keyup.enter.native="handleLogin"
          />
        </el-form-item>
        <img
          :src="imageCode"
          alt="codeImage"
          class="code-image"
          @click="getCodeImage"
        />
        <el-button
          :loading="loading"
          type="primary"
          style="width: 100%; margin-bottom: 14px"
          @click.native.prevent="handleLogin"
        >
          {{ $t("login.logIn") }}
        </el-button>
      </span>
      <span v-if="login.type === 'social'">
        {{ $t("login.chooseToSignIn") }}
        <div>
          <template v-for="(l, index) in logo">
            <div :key="index" class="logo-wrapper">
              <img
                :src="resolveLogo(l.img)"
                alt=""
                :class="{ radius: l.radius }"
                @click="socialLogin(l.name)"
              />
            </div>
          </template>
        </div>
      </span>
      <span v-if="login.type === 'tel'">
        <el-form-item prop="mobile">
          <el-input
            ref="mobile"
            v-model="loginForm.mobile"
            :placeholder="$t('login.tel')"
            prefix-icon="el-icon-user"
            name="mobile"
            type="text"
            autocomplete="off"
            @keyup.enter.native="telLogin"
          />
        </el-form-item>
        <el-form-item
          prop="smscode"
          style="width: 50%; float: left; margin-right: 2%"
        >
          <el-input
            ref="smscode"
            v-model="loginForm.smscode"
            prefix-icon="el-icon-lock"
            :placeholder="$t('login.code')"
            name="smscode"
            type="text"
            autocomplete="off"
            style="width: 70%"
            @keyup.enter.native="telLogin"
          />
        </el-form-item>
        <el-button
          type="warning"
          style="width: 46%; margin-right: 0; margin-top: 1%"
          size="medium"
          :disabled="!smsCodeShow"
          @click="getTelCode"
        >
          <span v-show="!smsCodeShow" class="count">请{{ count }}s后重试</span>
          <span v-show="smsCodeShow" class="count">获取验证码</span>
        </el-button>
        <el-button
          :loading="loading"
          type="primary"
          style="width: 100%; margin-bottom: 14px"
          @click.native.prevent="telLogin"
        >
          {{ $t("login.logIn") }}
        </el-button>
      </span>
      <span v-if="login.type === 'bind'" style="margin-top: -1rem">
        <el-tabs v-model="tabActiveName" @tab-click="handleTabClick">
          <el-tab-pane :label="$t('common.bindLogin')" name="bindLogin">
            <el-form-item prop="bindUsername">
              <el-input
                ref="bindUsername"
                v-model="loginForm.bindUsername"
                :placeholder="$t('login.username')"
                prefix-icon="el-icon-user"
                name="bindUsername"
                type="text"
                autocomplete="off"
              />
            </el-form-item>
            <el-form-item prop="bindPassword">
              <el-input
                ref="bindPassword"
                v-model="loginForm.bindPassword"
                :placeholder="$t('login.password')"
                prefix-icon="el-icon-key"
                name="bindPassword"
                type="password"
                :show-password="true"
                autocomplete="off"
              />
            </el-form-item>
            <el-button
              :loading="loading"
              type="primary"
              style="width: 100%; margin-bottom: 14px"
              @click.native.prevent="bindLogin"
            >
              {{ $t("common.bindLogin") }}
            </el-button>
          </el-tab-pane>
          <el-tab-pane :label="$t('common.signLogin')" name="signLogin">
            <el-form-item prop="signUsername">
              <el-input
                ref="signUsername"
                v-model="loginForm.signUsername"
                :placeholder="$t('login.username')"
                prefix-icon="el-icon-user"
                name="signUsername"
                type="text"
                autocomplete="off"
              />
            </el-form-item>
            <el-form-item prop="signPassword">
              <el-input
                ref="signPassword"
                v-model="loginForm.signPassword"
                :placeholder="$t('login.password')"
                prefix-icon="el-icon-key"
                name="signPassword"
                type="password"
                :show-password="true"
                autocomplete="off"
              />
            </el-form-item>
            <el-button
              :loading="loading"
              type="primary"
              style="width: 100%; margin-bottom: 14px"
              @click.native.prevent="signLogin"
            >
              {{ $t("common.signLogin") }}
            </el-button>
          </el-tab-pane>
        </el-tabs>
      </span>
      <el-dropdown class="login-type" placement="top-end">
        <span class="el-dropdown-link">
          <el-link type="primary">{{ $t("login.ortherLoginType") }}</el-link>
        </span>
        <el-dropdown-menu slot="dropdown">
          <el-dropdown-item
            :disabled="login.type === 'up'"
            @click.native="login.type = 'up'"
            >{{ $t("login.type.up") }}</el-dropdown-item
          >
          <el-dropdown-item
            :disabled="login.type === 'social'"
            @click.native="login.type = 'social'"
            >{{ $t("login.type.social") }}</el-dropdown-item
          >
          <el-dropdown-item
            :disabled="login.type === 'tel'"
            @click.native="login.type = 'tel'"
            >{{ $t("login.type.tel") }}</el-dropdown-item
          >
        </el-dropdown-menu>
      </el-dropdown>
    </el-form>
    <span class="login-footer">
      © 2020 <a target="_blank" href="">扫地僧_LLX</a> - CYH
    </span>
  </div>
</template>

<script>
import LangSelect from '@/components/LangSelect';
import db from '@/utils/localStorage';
import { randomNum } from '@/utils';
import axios from 'axios';
import { socialLoginUrl } from '@/settings';
import { validMobile } from '@/utils/my-validate'

const TIME_COUNT = 60; // 更改倒计时时间
export default {
  name: 'Login',
  components: { LangSelect },
  data() {
    return {
      count: '',
      smsCodeShow: true,
      timer: null,
      tabActiveName: 'bindLogin',
      codeUrl: `${process.env.VUE_APP_BASE_API}auth/captcha`,
      telCodeUrl: `${process.env.VUE_APP_BASE_API}auth/telCode`,
      socialLoginUrl: socialLoginUrl,
      login: {
        type: 'up'
      },
      logo: [
        { img: 'gitee.png', name: 'gitee', radius: true },
        { img: 'github.png', name: 'github', radius: true },
        { img: 'tencent_cloud.png', name: 'tencent_cloud', radius: true },
        { img: 'qq.png', name: 'qq', radius: false },
        { img: 'dingtalk.png', name: 'dingtalk', radius: true },
        { img: 'microsoft.png', name: 'microsoft', radius: false }
      ],
      loginForm: {
        username: '',
        password: '',
        bindUsername: '',
        bindPassword: '',
        signUsername: '',
        signPassword: '',
        mobile: '',
        smscode: ''
      },
      rules: {
        smscode: {
          required: true,
          message: this.$t('rules.require'),
          trigger: 'blur'
        },
        mobile: [
          {
            required: true,
            message: this.$t('rules.require'),
            trigger: 'blur'
          },
          {
            validator: (rule, value, callback) => {
              if (value !== '' && !validMobile(value)) {
                callback(this.$t('rules.mobile'))
              } else {
                callback()
              }
            }, trigger: 'blur'
          }
        ],
        username: {
          required: true,
          message: this.$t('rules.require'),
          trigger: 'blur'
        },
        password: {
          required: true,
          message: this.$t('rules.require'),
          trigger: 'blur'
        },
        code: {
          required: true,
          message: this.$t('rules.require'),
          trigger: 'blur'
        },
        bindUsername: {
          required: true,
          message: this.$t('rules.require'),
          trigger: 'blur'
        },
        bindPassword: {
          required: true,
          message: this.$t('rules.require'),
          trigger: 'blur'
        },
        signUsername: [
          {
            required: true,
            message: this.$t('rules.require'),
            trigger: 'blur'
          },
          {
            min: 4,
            max: 10,
            message: this.$t('rules.range4to10'),
            trigger: 'blur'
          }
        ],
        signPassword: [
          {
            required: true,
            message: this.$t('rules.require'),
            trigger: 'blur'
          },
          {
            min: 6,
            max: 20,
            message: this.$t('rules.range6to20'),
            trigger: 'blur'
          }
        ]
      },
      authUser: null,
      loading: false,
      showDialog: false,
      redirect: undefined,
      otherQuery: {},
      randomId: randomNum(24, 16),
      imageCode: '',
      page: {
        width: window.screen.width * 0.5,
        height: window.screen.height * 0.5
      }
    };
  },
  mounted() {
    db.clear();
    this.getCodeImage();
  },
  destroyed() {
    window.removeEventListener('message', this.resolveSocialLogin);
  },
  methods: {
    send() {
      if (!this.timer) {
        this.count = TIME_COUNT;
        this.smsCodeShow = false;
        this.timer = setInterval(() => {
          if (this.count > 0 && this.count <= TIME_COUNT) {
            this.count--;
          } else {
            this.smsCodeShow = true;
            clearInterval(this.timer); // 清除定时器
            this.timer = null;
          }
        }, 1000)
      }
    },
    getCodeImage() {
      axios({
        method: 'GET',
        url: `${this.codeUrl}?key=${this.randomId}`,
        responseType: 'arraybuffer'
      })
        .then(res => {
          return (
            'data:image/png;base64,' +
            btoa(
              new Uint8Array(res.data).reduce(
                (data, byte) => data + String.fromCharCode(byte),
                ''
              )
            )
          );
        })
        .then(res => {
          this.imageCode = res;
        })
        .catch(e => {
          if (e.toString().indexOf('429') !== -1) {
            this.$message({
              message: this.$t('tips.tooManyRequest'),
              type: 'error'
            });
          } else {
            this.$message({
              message: this.$t('tips.getCodeImageFailed'),
              type: 'error'
            });
          }
        });
    },
    getTelCode() {
      let mobile_c = false;
      this.$refs.loginForm.validateField('mobile', e => {
        debugger
        if (!e) {
          mobile_c = true;
        }
      });
      if (mobile_c) {
        this.send()
        axios({
          method: 'GET',
          url: `${this.telCodeUrl}?mobile=${this.loginForm.mobile}`,
          responseType: 'arraybuffer'
        })
          .then(res => {
            console.log(res)
            if (res.status == 200) {
              this.$message.success('验证码已下发，请查收！')
            }
          })
          .catch(e => {
          });
      }
    },
    handleTabClick(tab, event) {
      this.tabActiveName = tab.name;
    },
    resolveLogo(logo) {
      return require(`@/assets/logo/${logo}`);
    },
    socialLogin(oauthType) {
      const url = `${this.socialLoginUrl}/${oauthType}/login`;
      window.open(
        url,
        'newWindow',
        `resizable=yes, height=${this.page.height}, width=${this.page.width
        }, top=10%, left=10%, toolbar=no, menubar=no, scrollbars=no, resizable=no,location=no, status=no`
      );
      window.addEventListener('message', this.resolveSocialLogin, false);
    },
    resolveSocialLogin(e) {
      const data = e.data;
      const that = this;
      if (data.message === 'not_bind') {
        that.login.type = 'bind';
        const authUser = data.resultBody;
        that.authUser = authUser;
        that
          .$confirm(
            that.$t('common.current') +
            authUser.source +
            that.$t('common.socialAccount') +
            authUser.nickname +
            that.$t('common.socialTips'),
            that.$t('common.tips'),
            {
              confirmButtonText: that.$t('common.signLogin'),
              cancelButtonText: that.$t('common.bindLogin'),
              type: 'warning'
            }
          )
          .then(() => {
            that.tabActiveName = 'signLogin';
          })
          .catch(() => {
            that.tabActiveName = 'bindLogin';
          });
      } else if (data.message === 'social_login_success') {
        that.saveLoginData(data.resultBody.token);
        that.getUserDetailInfo();
        that.loginSuccessCallback();
      } else {
        // do nothing
      }
    },
    bindLogin() {
      let username_c = false;
      let password_c = false;
      this.$refs.loginForm.validateField('bindUsername', e => {
        if (!e) {
          username_c = true;
        }
      });
      this.$refs.loginForm.validateField('bindPassword', e => {
        if (!e) {
          password_c = true;
        }
      });
      if (username_c && password_c) {
        this.loading = true;
        const that = this;
        const params = {
          bindUsername: that.loginForm.bindUsername,
          bindPassword: that.loginForm.bindPassword,
          ...that.authUser
        };
        params.token = null;
        that
          .$post('auth/social/bind/login', params)
          .then(r => {
            const data = r.data.data;
            this.saveLoginData(data);
            this.getUserDetailInfo();
            this.loginSuccessCallback();
          })
          .catch(error => {
            console.error(error);
            that.loading = false;
          });
      }
    },
    signLogin() {
      let username_c = false;
      let password_c = false;
      this.$refs.loginForm.validateField('signUsername', e => {
        if (!e) {
          username_c = true;
        }
      });
      this.$refs.loginForm.validateField('signPassword', e => {
        if (!e) {
          password_c = true;
        }
      });
      if (username_c && password_c) {
        this.loading = true;
        const that = this;
        const params = {
          bindUsername: that.loginForm.signUsername,
          bindPassword: that.loginForm.signPassword,
          ...that.authUser
        };
        params.token = null;
        that
          .$post('auth/social/sign/login', params)
          .then(r => {
            const data = r.data.data;
            this.saveLoginData(data);
            this.getUserDetailInfo();
            this.loginSuccessCallback();
          })
          .catch(error => {
            console.error(error);
            that.loading = false;
          });
      }
    },
    telLogin() {
      let mobile_c = false;
      let smscode_c = false;
      this.$refs.loginForm.validateField('mobile', e => {
        if (!e) {
          mobile_c = true;
        }
      });
      this.$refs.loginForm.validateField('smscode', e => {
        if (!e) {
          smscode_c = true;
        }
      });
      if (mobile_c && smscode_c) {
        var loginForm = this.loginForm;
        this.loading = true;
        const that = this;
        this.$login('auth/oauth/token', {
          ...loginForm,
          grant_type: 'mobile_smscode'
        })
          .then(r => {
            const data = r.data;
            this.saveLoginData(data);
            this.getUserDetailInfo();
            this.loginSuccessCallback();
          })
          .catch(error => {
            console.error(error);
            that.loading = false;
          });
      }
    },
    handleLogin() {
      let username_c = false;
      let password_c = false;
      let code_c = false;
      this.$refs.loginForm.validateField('username', e => {
        if (!e) {
          username_c = true;
        }
      });
      this.$refs.loginForm.validateField('password', e => {
        if (!e) {
          password_c = true;
        }
      });
      this.$refs.loginForm.validateField('code', e => {
        if (!e) {
          code_c = true;
        }
      });
      if (username_c && password_c && code_c) {
        this.loading = true;
        const that = this;
        this.$login('auth/oauth/token', {
          ...that.loginForm,
          key: this.randomId
        })
          .then(r => {
            const data = r.data;
            this.saveLoginData(data);
            this.getUserDetailInfo();
            this.loginSuccessCallback();
          })
          .catch(error => {
            console.error(error);
            that.loading = false;
            that.getCodeImage();
          });
      }
    },
    saveLoginData(data) {
      this.$store.commit('account/setAccessToken', data.access_token);
      this.$store.commit('account/setRefreshToken', data.refresh_token);
      const current = new Date();
      const expireTime = current.setTime(
        current.getTime() + 1000 * data.expires_in
      );
      this.$store.commit('account/setExpireTime', expireTime);
    },
    getUserDetailInfo() {
      this.$get('auth/user')
        .then(r => {
          this.$store.commit('account/setUser', r.data.principal);
          this.$message({
            message: this.$t('tips.loginSuccess'),
            type: 'success'
          });
          this.loading = false;
          const redirectUrl = decodeURIComponent(
            this.$route.query.redirect || '/home'
          );
          this.$router.push({ path: redirectUrl });
        })
        .catch(error => {
          this.$message({
            message: this.$t('tips.loginFail'),
            type: 'error'
          });
          console.error(error);
          this.loading = false;
        });
    },
    loginSuccessCallback() {
      this.$get('system/user/success/').catch(e => {
        console.log(e);
      });
    }
  }
};
</script>

<style lang="scss">
@import "login";
</style>
<style lang="scss" scoped>
@import "login-scoped";
</style>
